/** @file oal_workqueue.h
 *  @brief This header file contains workqueue abstract layger
 *
 *  Copyright (C) 2022, Artosyn Technologies. ALL RIGHTS RESERVED.
 *
 *  This Information is proprietary to Artosyn Technologies and MAY NOT
 *  be copied by any method or incorporated into another program without
 *  the express written consent of Artosyn. This Information or any portion
 *  thereof remains the property of Artosyn. The Information contained herein
 *  is believed to be accurate and Artosyn assumes no responsibility or
 *  liability for its use in any way and conveys no license or title under
 *  any patent or copyright and makes no representation or warranty that this
 *  Information is free from patent or copyright infringement.
 *
 */

#ifndef _OAL_WORKQUEUE_H_
#define _OAL_WORKQUEUE_H_

#include <linux/workqueue.h>
#include "oal_main.h"

typedef void (*ar_work_func)(oal_handle *poal_handle, void* priv);
typedef struct _oal_workqueue oal_workqueue;

/** Work_queue work initialization */
#define OAL_INIT_WORK                              INIT_WORK
/** Work_queue delayed work initialization */
#define OAL_INIT_DELAYED_WORK                      INIT_DELAYED_WORK
/** Work_queue container parameter */
#define OAL_DELAYED_CONTAINER_OF(_ptr, _type, _m)  container_of(_ptr, _type, _m.work)

/** oal workqueue state */
enum {
    OAL_WORKQUEUE_STATE_IDLE,
    OAL_WORKQUEUE_STATE_RUN,
    OAL_WORKQUEUE_STATE_STOP
};

struct _oal_workqueue {
    /** oal_handle structure pointer */
    oal_handle *handle;

    /** workqueue */
    struct workqueue_struct *workqueue;
    /** work */
    struct work_struct work;
    /** work func */
    ar_work_func ar_func;
    /** priv data */
    void* priv;

    /** spin lock for workqueue */
    spinlock_t lock;
    /** workqueue processing state */
    volatile u32 state;
};

/**
 *  @brief Iinit the workqueue and register the process func
 *
 *  @param handle           A pointer to oal_handle structure
 *  @param ar_workqueue     (OUT)A pointer to oal_workqueue structure
 *  @param name             Name of the workqueue
 *  @param flags            Flag of the workqueue
 *  @param ar_func          Process func
 *  @param priv             Private data
 *
 *  @return OAL_STATUS_SUCCESS or OAL_STATUS_FAILURE
 */
oal_status oal_init_workqueue(oal_handle *handle, oal_workqueue **ar_workqueue, const char *name, unsigned int flags, ar_work_func ar_func, void* priv);

/**
 *  @brief  Deinit the workqueue
 *
 *  @param  handle           A pointer to oal_handle structure
 *  @param  ar_workqueue     A pointer to oal_workqueue structure
 *
 *  @return N/A
 */
void oal_deinit_workqueue(oal_handle *handle, oal_workqueue *ar_workqueue);

/**
 *  @brief  queue_work the workqueue
 *
 *  @param  handle           A pointer to oal_handle structure
 *  @param  ar_workqueue     A pointer to oal_workqueue structure
 *
 *  @return N/A
 */
void oal_queue_work(oal_handle *handle, oal_workqueue *ar_workqueue);

/**
 *  @brief  Stop the workqueue
 *
 *  @param  handle           A pointer to oal_handle structure
 *  @param  ar_workqueue     A pointer to oal_workqueue structure
 *
 *  @return N/A
 */
void oal_stop_workqueue(oal_handle *handle, oal_workqueue *ar_workqueue);

#endif /* _OAL_WORKQUEUE_H_ */
